package cn.kailangtu.serialutils.api;

import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.SystemClock;
import android.util.Log;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import java.util.List;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;

import cn.kailangtu.commontools.AppVariable;
import cn.kailangtu.commontools.CommonUtils;
import cn.kailangtu.commontools.Loggers;
import cn.kailangtu.serialutils.ComTrUsb;
import cn.kailangtu.serialutils.ReceiveDataCallback;
//import cn.wch.uartlib.WCHUARTManager;

public class SerialPortApi {

    private Context context;
    private static String TAG = "SerialPortApi==>";
    private String portName;
    private int baudrate;
    private int flags;
    private LinkedBlockingQueue<String> reportMsgQueue = null;
    private LinkedBlockingQueue<String> sendMsgQueue = null;
    private LinkedBlockingQueue<String> sourceMsgQueue = null;
    private static boolean isProcess = false;
    private static boolean isSending = false;
    private static boolean isSpying = false;
    private static boolean isProcessMsg = false;
    private ReceiveLogMessageListenerV2 logMsgListne = null;

    private long lastReceiveTime =0;


    private static SerialPortApi instance = null;

    private  byte[] rxByteArray;
    private  int resultSize;

    private SerialPortApi(){
        reportMsgQueue = new LinkedBlockingQueue<>(500);
        sendMsgQueue = new LinkedBlockingQueue<>(500);
        sourceMsgQueue = new LinkedBlockingQueue<>(500);

        /*
        SpyThread thread = new SpyThread();
        thread.start();

         */

        SendThread sendThread =new SendThread();
        sendThread.start();

        ProcessThread processThread = new ProcessThread();
        processThread.start();

        ProcessSourceThread processSourceThread = new ProcessSourceThread();
        processSourceThread.start();
    }


    public static SerialPortApi getInstance() {
        if(instance ==null)
        {
            instance = new SerialPortApi();
        }
        return instance;
    }

    public void Init(Application context,ReceiveLogMessageListenerV2 logListner){
        //ComTrUsb.getInstance().initContext(context);
        this.context = context;
        this.logMsgListne = logListner;
    }

    public boolean isOpen(){
        if(AppVariable.platform_version == 450)
            return true;
        if(port != null) {
            return port.isOpen();
        }
        return false;
    }

    public boolean isOpenEx()
    {
        return ComTrUsb.isOpen;
    }
    UsbSerialPort port;
    public boolean openSerialPortV2(String portName,int baudrate,int flags){
        int count = 0;
        this.baudrate = baudrate;
        openUsb();
//       while(!openUsb() && count < 3)
//       {
//
//           SystemClock.sleep(100);
//           count++;
//           Log.e("COMCOM","打开次数："+count);
//       }
       return isOpen();

    }

    long sendCount,receiveCount;

    private boolean openUsb()
    {
        try {
            // Find all available drivers from attached devices.
            UsbManager manager = (UsbManager) this.context.getSystemService(Context.USB_SERVICE);
            List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
            if (availableDrivers.isEmpty()) {
                return false;
            }


            // Open a connection to the first available driver.
            UsbSerialDriver driver = availableDrivers.get(0);


            //WCHUARTManager.getInstance().requestPermission(context, driver.getDevice());
            //SystemClock.sleep(200);

            Intent intent = new Intent("com.exmple.USB_PERMISSION");//发送自定义广播
            PendingIntent pendingIntent =
                    PendingIntent.getBroadcast(context.getApplicationContext(), 0, intent, 0);
            manager.requestPermission(driver.getDevice(),pendingIntent);
            SystemClock.sleep(200);

            // Open a connection to the first available driver.
            UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
            if (connection == null) {
                // add UsbManager.requestPermission(driver.getDevice(), ..) handling here
                return false;
            }

            port = driver.getPorts().get(0); // Most devices have just one port (port 0)
            port.open(connection);
            port.setParameters(256000, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

            SerialInputOutputManager serialInputOutputManager =   new SerialInputOutputManager(port, new SerialInputOutputManager.Listener() {
                @Override
                public void onNewData(byte[] data) {
                    String strData = CommonUtils.ByteArrayToHexString(data);

                        Log.d("COMCOM", strData);

                  // Loggers.testInfo(strData);

                    lastReceiveTime = System.currentTimeMillis();
                    receiveCount++;
                    Log.d("COMCOM COUNT","receive count:"+receiveCount);
                    Log.d("FFFFFFFFFFFFFFFFFFFF","TIME:"+(lastReceiveTime- lastSendTime2));

                    sourceMsgQueue.offer(strData);
                }

                @Override
                public void onRunError(Exception e) {
                    Loggers.errInfo("串口异常："+e.getMessage());
                }
            });

            serialInputOutputManager.start();
            return true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }



    /***
     * 打开串口
     * @param portName 串口名称，例：/dev/ttyS1
     * @param baudrate 波特率
     * @param flags flag
     * @return
     */
    public boolean openSerialPortV2Ex(String portName,int baudrate,int flags)
    {
        this.baudrate = baudrate;
        ComTrUsb.getInstance().openCOM(baudrate);
        if(ComTrUsb.isOpen) {
            showMsg("打开成功");
            Log.d("COMCOM","打开成功");
            ComTrUsb.getInstance().setDataCallback(new ReceiveDataCallback() {
                @Override
                public void onReceiveData(String data) {

                    Log.d("COMCOM",data);
                  //  Loggers.netInfo("RECEIVE:"+data);
                    lastReceiveTime = System.currentTimeMillis();
                   // sourceMsgQueue.offer(data);
                    byte[] dataArr = CommonUtils.hexStringToByteArray(data);
                    onDataReceived(dataArr, dataArr.length);
                }
            });
        }
        else{
            showMsg("打开失败");
            SystemClock.sleep(2000);
            openSerialPortV2Ex(portName,baudrate,flags);
        }
        return ComTrUsb.isOpen;
    }



    public void closeEx(){
        ComTrUsb.getInstance().closeCom();
       // WCHUARTManager.getInstance().close(context);
    }

    public void close(){
        try {
            port.close();
        }
        catch(Exception e)
        {
            Loggers.errInfo("关闭串口异常:"+e.getMessage());
        }
    }





    public void addSendString(String data){
        try {
            sendMsgQueue.offer(data);
            //port.write(CommonUtils.hexStringToByteArray(data), 100);
        }
        catch(Exception e)
        {
            Loggers.errInfo("写数据异常："+e.getMessage());
        }

    }

    private void sendStringEx(String data)
    {
        showMsg("发送数据："+data);
        //Log.e("COMCOM",data);
        Loggers.netInfo("SEND:"+data);
        ComTrUsb.getInstance().sendCMD(CommonUtils.hexStringToByteArray(data));
    }


    private void reOpen(){

        try{

            closeEx();
            SystemClock.sleep(500);

        }
        catch(Exception e){}
        openSerialPortV2Ex(this.portName,this.baudrate,this.flags);

    }



    public long getLastReceiveTime(){
        return lastReceiveTime;
    }

    public void setLastReceiveTime(long lastReceiveTime)
    {
        this.lastReceiveTime = lastReceiveTime;
    }


    private class SpyThread extends Thread{
        @Override
        public void run(){
            super.run();
            if(!isSpying)
            {
                isSpying = true;
                while(true){

                    if(ComTrUsb.isOpen &&  (System.currentTimeMillis() - lastReceiveTime) > 20000)
                    {
                        lastReceiveTime = System.currentTimeMillis();
                        //reOpen();
                    }
                    SystemClock.sleep(1000);
                }
            }
        }
    }

    long lastSendTime2 = 0;
    long lastReceiveTime2 = 0;

    private class SendThread extends Thread{
        @Override
        public void run(){
            super.run();
            if(!isSending){
                isSending = true;
                while(true){
                    try {
                        String currentCmd = sendMsgQueue.take();
                        port.write(CommonUtils.hexStringToByteArray(currentCmd), 100);
                        lastSendTime2 = System.currentTimeMillis();
                        sendCount++;
                        Log.d("COMCOM COUNT","send count:"+sendCount);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                //isSending = false;
            }
        }
    }

    private class ProcessSourceThread extends Thread{
        @Override
        public void run(){
            super.run();
            if(!isProcessMsg){
                isProcessMsg = true;
                while(true){
                    try {
                        String currentCmd = sourceMsgQueue.take();
                       // Log.e("COMCOM","TAKE:"+currentCmd);
                        byte[] dataArr = CommonUtils.hexStringToByteArray(currentCmd);
                        onDataReceived(dataArr, dataArr.length);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private class ProcessThread extends  Thread{
        @Override
        public void run(){
            super.run();
            if(!isProcess) {
                isProcess = true;
                while(!isInterrupted()){

                    try {
                        String currentCmd = reportMsgQueue.take();
                        Loggers.hardwareInfo("RECEIVE:"+currentCmd);
                        DataVersion2 dataVersion2 =  DataVersion2.build(currentCmd);

                        if(dataVersion2.getAddress() == 1)
                        {
                            Com1.getInstance().receiveData(dataVersion2.getData());
                        }
                        else  if(dataVersion2.getAddress() == 2)
                        {
                            Com2.getInstance().receiveData(dataVersion2.getData());
                        }
                        else  if(dataVersion2.getAddress() == 3)
                        {
                            Com3.getInstance().receiveData(dataVersion2.getData());
                        }
                        else  if(dataVersion2.getAddress() == 4)
                        {
                            Com4.getInstance().receiveData(dataVersion2.getData());
                        }
                        else  if(dataVersion2.getAddress() == 5)
                        {
                            Com5.getInstance().receiveData(dataVersion2.getData());
                        }
                        else if(dataVersion2.getAddress() == 6){
                            //Loggers.errInfo("进入了6");
                            if(dataVersion2.getData().length == 3)
                            {
                                //Loggers.errInfo("进入了6,长度3");
                                DIManager.getInstance().newValue(dataVersion2.getData()[0],dataVersion2.getData()[1],dataVersion2.getData()[2]);
                            }
                            else{
                                //Loggers.errInfo("进入了6,长度"+dataVersion2.getData().length);
                            }
                        }
                        else if(dataVersion2.getAddress() == 7){
                            if(dataVersion2.getData().length == 3)
                            {
                                InfraredManager.getInstance().newValue(dataVersion2.getData()[0],dataVersion2.getData()[1],dataVersion2.getData()[2]);
                            }
                        }
                        else if(dataVersion2.getAddress() == 8){
                            Com6.getInstance().receiveData(dataVersion2.getData());
                        }

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
                isProcess = false;
            }
        }
    }


    private  void onDataReceived(byte[] paramArrayOfByte,
                                       int paramInt) {

        rxByteArray = CommonUtils.ArrayAppend(rxByteArray, paramArrayOfByte, paramInt);
        if (rxByteArray == null) {
            return;
        }
       // String byteStr = CommonUtils.ByteArrayToHexString(rxByteArray);
       // showMsg("receive msg:"+byteStr.toUpperCase());
        resultSize += paramInt;

        if(isComplete())
        {
            resultSize = 0;
            rxByteArray = null;
        }



    }



    private boolean isComplete() {
        if (rxByteArray != null && rxByteArray.length > 1
                && (rxByteArray[rxByteArray.length - 2] & 0xFF) == 0x7D
                && (rxByteArray[rxByteArray.length - 1] & 0xFF) == 0x7D
        ) {

            List<String> lsCmd = DataAnalysis.GetCmd(CommonUtils.ByteArrayToHexString(rxByteArray).toUpperCase());
            for (String cmd : lsCmd) {
                Loggers.errInfo("完整数据："+cmd);
                reportMsgQueue.offer(cmd);
            }

            return true;
        }
        else{
           // Log.e("COMCOM",CommonUtils.ByteArrayToHexString(rxByteArray));
        }
        return false;
    }


    public static void sendKeyboardEvent(int keyCode)
    {
        try{
            String keyCommand = "input keyevent "+keyCode;
            Runtime.getRuntime().exec(keyCommand);
            Log.e("KEYBOARD",keyCommand);
        }
        catch(Exception e)
        {
            Log.e("KEYBOARD",e.getMessage());
            e.printStackTrace();
        }
    }

    public  void toTest(int count)
    {
        ProcessThread processThread = new ProcessThread();
        processThread.start();
        Random r = new Random();
        while(count > 0)
        {
            count--;
            DataVersion2 newData =   DataVersion2.build(1,new byte[]{0,1,2,3,4,5,6,7,8,9,0x10,0x11,0x12,0x13});

            String cmd = newData.getCmdString();
            reportMsgQueue.offer(cmd);
            SystemClock.sleep(r.nextInt(1000));
        }
    }

    public void showMsg(String message){
        if(logMsgListne != null)
        {
            logMsgListne.onLogMessage(message);
        }
    }

    boolean isSpy = false;



    public void closeSpy(){
        isSpy = false;
    }
}
